package com.example.jsonp;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.DBConnection;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.thymeleaf.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class JsonpDemo {
    private static String domian = "https://www.jsczc.com";

    //数据库配置
    public static String dburl = "jdbc:mysql://localhost:3306/etl?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
    public static String driver = "com.mysql.cj.jdbc.Driver";
    public static String username = "root";
    public static String password = "123456";

    static Connection conn = DBConnection.getConnection(driver, dburl, username, password);


    public static void puqu() throws Exception {
        //创建线程池
        ExecutorService pageService = Executors.newFixedThreadPool(50);
        ExecutorService figureService = Executors.newFixedThreadPool(100);
        //获取地址
        String url = "https://www.jsczc.com/nvyou/index.html";

        Document document = Jsoup.connect(url).timeout(60000).get();
        Element body = document.body();
        Elements elements = body.select("a");
        //初始化分页
        List<String> pageList = new ArrayList<>();
        for (Element element : elements) {
            String link = element.attr("href");
            if (link.contains("/nvyou/index_")) {
                //获取分页
                pageList.add(link);
            }
        }
        pageList = countPage(pageList,url);
        //创建线程任务
        CompletableFuture[] pageFutures = new CompletableFuture[pageList.size()];
        for (int i = 0; i < pageList.size(); i++) {
            String pageUrl = pageList.get(i);
            CompletableFuture<Void> integerCompletableFuture = CompletableFuture.runAsync(() -> {
                //TODO-----执行人物列表方法开始
                try {
                    //获取人物列表
                    List<Figure> figureList = getPageListUrl(pageUrl);
                    if(figureList.size() == 0){
                        return;
                    }
                    CompletableFuture[] figureFutures = new CompletableFuture[figureList.size()];
                    for (int i1 = 0; i1 < figureList.size(); i1++) {
                        Figure figure = figureList.get(i1);
                        conn.prepareStatement(sqlFigureCreate(figure)).execute();
                        CompletableFuture<Void> figureCompletableFuture = CompletableFuture.runAsync(() -> {
                        //TODO-----执行作品列表方法开始
                        //获取作品列表
                            try {
                                List<Works> worksList = getWorksList(figure);
                                if(worksList.size() == 0){
                                    return;
                                }
                                for (Works works : worksList) {
                                    //获取作品详情
                                    WorksInfo worksInfo = getWorksDetail(works,figure);
                                    conn.prepareStatement(sqlWorksCreate(worksInfo)).execute();
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            //TODO-----执行作品列表方法结束
                        }, figureService);
                        figureFutures[i1] = figureCompletableFuture;
                    }
                    //等待线程执行完
                    CompletableFuture.allOf(figureFutures).join();

                } catch (Exception e) {
                    e.printStackTrace();
                }
                //TODO-----执行人物列表方法结束
            }, pageService);
            pageFutures[i] = integerCompletableFuture;

        }
        //等待线程执行完
        CompletableFuture.allOf(pageFutures).join();

    }

    public static WorksInfo getWorksDetail(Works works,Figure figure)throws Exception{
        Document document = Jsoup.connect(works.getLink()).timeout(60000).get();
        Element body = document.body();
        Elements elements = body.select("div");
        WorksInfo info = new WorksInfo();
        for (Element element : elements) {
            if(element.className().equals("content loadimg")){
                Elements spanList = element.select("p");
                for (Element span : spanList) {
                    String text = span.select("b").first().text();
                    switch (text){
                        case "番号封面：":
                            String img = element.select("img").first().attr("src");
                            info.setHttpCover(img);
                            info.setCover(downloadPicture(img,works.getName(),"E:\\AV\\" + figure.getName()));
                            break;
                        case "作品番号：":
                            info.setNumber(span.text().replace("作品番号：",""));
                            System.out.println("执行番号----------------------"+ figure.getName() + "-------" + info.getNumber());
                            break;
                        case "主演女优：":
                            info.setFigure(span.text().replace("主演女优：",""));
                            break;
                        case "发片时间：":
                            info.setIssueDate(span.text().replace("发片时间：",""));
                            break;
                        case "作品时长：":
                            info.setDuration(span.text().replace("作品时长：",""));
                            break;
                        case "地区分类：":
                            info.setRegion(span.text().replace("地区分类：",""));
                            break;
                        case "分类标签：":
                            info.setTags(span.text().replace("分类标签：",""));
                            break;
                        case "发行片名：":
                            info.setName(span.text().replace("发行片名：",""));
                            break;
                    }
                }

            }
        }
        return info;

    }


    /**
     * 获取作品列表
     * @param figure
     * @return
     * @throws IOException
     */
    public static List<Works> getWorksList(Figure figure) throws Exception {
        List<Works> list = new ArrayList<>();
        Document document = Jsoup.connect(figure.getLink()).timeout(60000).get();
        Element body = document.body();
        Elements elements = body.select("a");
        //获取每一页作品
        for (Element element : elements) {
            String link = element.attr("href");
            if(link.contains("/fanhao/")) {
                Elements p = element.select("p");
                if(p.size() == 0){
                    continue;
                }
                Works works = new Works();
                //获取番号
                works.setName(p.first().text());
                //获取作品连接
                works.setLink(domian + link);
                //获取作品图片
                works.setImg("E:\\AV\\" + figure.getName() + "\\" + works.getName() + "\\" +  works.getName() + ".jpg");
                list.add(works);
            }
        }
        return list;
    }

    /**
     * 获取人物列表
     * @param url
     * @return
     * @throws IOException
     */
    public static List<Figure> getPageListUrl(String url) throws Exception {
        List<Figure> list = new ArrayList<>();
        Document document = Jsoup.connect(url).timeout(60000).get();
        Element body = document.body();

        Elements elements = body.select("a");
        //获取每一页作品
        for (Element element : elements) {
            String link = element.attr("href");
            if(!link.contains("/nvyou/index_") && link.contains("/nvyou/") && !link.equals("/nvyou/")) {
                Elements p = element.select("p");
                if(p.size() == 0){
                    continue;
                }
                Figure figure = new Figure();
                //获取人物名称
                figure.setName(p.first().text());
                //获取人物作品连接
                figure.setLink(domian + link);
                //获取人物图片
                String img = "https://" + element.select("img").first().attr("src").replace("//","");
                figure.setImg(downloadPicture(img,figure.getName(),"E:\\AV"));
                list.add(figure);
            }
        }
        return list;
    }

    /**
     * 初始化分页
     * @param data
     * @return
     */
    public static List<String> countPage(List<String> data,String firstUrl) {
        List<String> linkList = new ArrayList<>();
        linkList.add(firstUrl);
        String url = "https://www.jsczc.com/nvyou/index_%s.html";
        //获取页面
        int current = Integer.parseInt(data.get(0).replaceAll("/nvyou/index_","").replaceAll(".html",""));
        int lastCurrent = Integer.parseInt(data.get(data.size() - 1).replaceAll("/nvyou/index_","").replaceAll(".html",""));
        while (current <= lastCurrent){
            linkList.add(String.format(url,current));
            current ++;
        }
        return linkList;
    }

    public static String downloadPicture(String urlPath, String fileName, String filePath) {
        if (StringUtils.isEmpty(urlPath)) {//可能混杂一些空链接.需要处理
            return "";
        }
        CloseableHttpClient httpClient = null;
        InputStream inputStream = null;
        File file = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpGet method = new HttpGet(urlPath);
            HttpResponse result = httpClient.execute(method);
            inputStream = result.getEntity().getContent();
            //得到图片的二进制数据,以二进制封装得到数据,具有通用性
            byte[] data = readInputStream(inputStream);
            //new一个文件对象用来保存图片,默认保存当前工程根目录
            File isexits = new File(filePath + "\\" + fileName);
            if (!isexits.exists()) {
                isexits.mkdirs();
            }
            /**
             *
             * 问题解决:outputstream流不能直接创建文件夹,所以在直接写不存在的文件夹的时候会出现问题,这个时候在前面进行一个文件夹是否存在的判断,
             * 若存在,直接存储不会出现问题,
             * 若不存在,需要先创建一个文件夹才可以
             */
            File imageFile = new File(filePath + "\\" + fileName + "\\" + fileName + ".jpg");
            //创建输出流
            FileOutputStream outStream = new FileOutputStream(imageFile);
            //写入数据
            outStream.write(data);
            //关闭输出流
            outStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {

            }
            try {
                httpClient.close();
            } catch (IOException e) {

            }
            return filePath + "\\" + fileName + "\\" + fileName + ".jpg";
        }

    }

    public static byte[] readInputStream(InputStream inStream) throws Exception{
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //创建一个Buffer字符串
        byte[] buffer = new byte[1024];
        //每次读取的字符串长度,如果为-1,代表全部读取完毕
        int len = 0;
        //使用一个输入流从buffer里把数据读取出来
        while( (len=inStream.read(buffer)) != -1 ){
            //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
            outStream.write(buffer, 0, len);
        }
        //关闭输入流
        inStream.close();
        //把outStream里的数据写入内存
        return outStream.toByteArray();
    }

    public static String sqlFigureCreate(Figure figure){
        //存入数据库
        StringBuilder sql = new StringBuilder();
        sql.append("insert into av_performer(id, name, imgPath) values(")
                .append("'").append(UUID.randomUUID().toString()).append("',")
                .append("'").append(figure.getName()).append("',")
                .append("'").append(figure.getImg().replaceAll("\\\\","/")).append("'").append(")");
        return sql.toString();
    }

    public static String sqlWorksCreate(WorksInfo works){
        //存入数据库
        StringBuilder sql = new StringBuilder();
        sql.append("insert into av_works(id,name,performer,time,area,label,content,imgPath,localexist,localPath) values(")
                .append("'").append(UUID.randomUUID().toString()).append("',")
                .append("'").append(works.getNumber()).append("',")
                .append("'").append(works.getFigure()).append("',")
                .append("'").append(works.getIssueDate()).append("',")
                .append("'").append(works.getDuration()).append("',")
                .append("'").append(works.getRegion()).append("',")
                .append("'").append(works.getTags()).append("',")
                .append("'").append(works.getHttpCover()).append("',")
                .append("'").append(0).append("',")
                .append("'").append(works.getCover().replaceAll("\\\\","/")).append("'").append(")");
        return sql.toString();
    }

    public static void main(String[] args) throws Exception {
        System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
        System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
        System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "stdout");
        puqu();
//        System.out.println(JSONObject.toJSONString(getWorksDetail(null)));
//        System.out.println(regexM("/nvyou/index_2.html","^/nvyou/index\\_\\d.html$"));
    }
}
